package com.yang.newRetail.model;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.yang.newRetail.utils.LowercaseUnderline;

import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;

public class GenericHandleMany<M, E, P, N> {

    private M oneMapper;
    private E entity;
    private P manyMapper;
    private N many;

    public GenericHandleMany(M oneMapper, E entity, P manyMapper, N many) {
        this.oneMapper = oneMapper;
        this.entity = entity;
        this.manyMapper = manyMapper;
        this.many = many;
    }

    public M getOneMapper() {
        return oneMapper;
    }

    public void setOneMapper(M oneMapper) {
        this.oneMapper = oneMapper;
    }

    public E getEntity() {
        return entity;
    }

    public void setEntity(E entity) {
        this.entity = entity;
    }

    public P getManyMapper() {
        return manyMapper;
    }

    public void setManyMapper(P manyMapper) {
        this.manyMapper = manyMapper;
    }

    public N getMany() {
        return many;
    }

    public void setMany(N many) {
        this.many = many;
    }

    public void manyCreated(String related, String pk, String fk) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException, InstantiationException {
        Class com = oneMapper.getClass();
        Class ce = entity.getClass();
        Class cmm = manyMapper.getClass();
        Class cm = many.getClass();

        Field id = ce.getDeclaredField("id");
        id.setAccessible(true);
        String reallyId = (String) id.get(entity);

        Field relatedField = ce.getDeclaredField(related);
        relatedField.setAccessible(true);
//        List<N> fs = (List<N>) relatedField.get(entity);
        List<String> fs = (List<String>) relatedField.get(entity);

        Field manyId = cm.getDeclaredField(fk);
        Field oneId = cm.getDeclaredField(pk);
        manyId.setAccessible(true);
        oneId.setAccessible(true);

        Method mcmm = cmm.getMethod("insert", Object.class);
        for (String s : fs
             ) {
            Constructor ccm = cm.getConstructor();
            N ncm = (N) ccm.newInstance();

            manyId.set(ncm, s);
            oneId.set(ncm,reallyId);

            mcmm.invoke(manyMapper, ncm);
        }

        Method mcom = com.getMethod("insert", Object.class);
        mcom.invoke(oneMapper, entity);
    }

    public void manyDelete(String related) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException {
        Class com = oneMapper.getClass();
        Class ce = entity.getClass();
        Class cmm = manyMapper.getClass();

        Field id = ce.getDeclaredField("id");
        id.setAccessible(true);
        String pk = (String) id.get(entity);

        Method mcmm = cmm.getMethod("delete", Wrapper.class);
        QueryWrapper<N> nwrapper = new QueryWrapper<>();
        nwrapper.eq(related, pk);
        mcmm.invoke(manyMapper, nwrapper);

        Method mm = com.getMethod("deleteById", Serializable.class);
        mm.invoke(oneMapper, pk);
    }

    public void manyUpdate(String related, String pk, String fk) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, NoSuchFieldException, InstantiationException {
        Class com = oneMapper.getClass();
        Class ce = entity.getClass();
        Class cmm = manyMapper.getClass();
        Class cm = many.getClass();

        Field id = ce.getDeclaredField("id");
        id.setAccessible(true);
        String reallyId = (String) id.get(entity);

        Method dmcmm = cmm.getMethod("delete", Wrapper.class);
        QueryWrapper<N> nwrapper = new QueryWrapper<>();
        nwrapper.eq(LowercaseUnderline.upperCharToUnderLine(pk), reallyId);
        dmcmm.invoke(manyMapper, nwrapper);

        Field relatedField = ce.getDeclaredField(related);
        relatedField.setAccessible(true);
//        List<N> fs = (List<N>) relatedField.get(entity);
        List<String> fs = (List<String>) relatedField.get(entity);

        Field manyId = cm.getDeclaredField(fk);
        Field oneId = cm.getDeclaredField(pk);
        manyId.setAccessible(true);
        oneId.setAccessible(true);

        Method imcmm = cmm.getMethod("insert", Object.class);
        for (String s : fs
        ) {
            Constructor ccm = cm.getConstructor();
            N ncm = (N) ccm.newInstance();

            manyId.set(ncm, s);
            oneId.set(ncm,reallyId);

            imcmm.invoke(manyMapper, ncm);
        }

        Method mcom = com.getMethod("updateById", Object.class);
        mcom.invoke(oneMapper, entity);
    }
}
